import { v4 as uuid } from 'uuid'
import { StdBlock } from './block'
import { StdNote, StdNoteTextDataV2 } from './note'
import { StdTextsV2 } from './textData'
import { StdParagraphV2 } from './paragraph'
import store from '@/store'

export class StdTableDataV2 {
  constructor({ dataId, tableNumber = 1, captionZh, captionEn, thead, tbody, tfoot ,variableId}) {
    // 数据唯一标识
    this.dataId = dataId || uuid()
    // 表的编号
    this.tableNumber = tableNumber
    // 中文标题和单位
    this.captionZh = captionZh ? new StdTableCaption(captionZh) : null
    // 英文标题和单位
    this.captionEn = captionEn ? new StdTableCaption(captionEn) : null
    // 表头
    this.thead = thead?.tr ? new StdTheadV2(thead) : null
    // 表格
    this.tbody = tbody?.tr ? new StdTbodyV2(tbody) : null
    // 表尾 默认只有表注或者脚注
    this.tfoot = tfoot?.tr ? new StdTfootV2(tfoot) : null
    this.variableId = variableId
  }
}

class StdTableCaption {
  constructor({ dataId, title, unit }) {
    this.dataId = dataId || uuid()
    this.title = title
    // 单位
    this.unit = unit
  }
}

class StdThOrTd {
  constructor({ dataId, referId, colspan = 1, rowspan = 1, blockList = [], isRevised = false, width, height }) {
    // 数据唯一标识
    this.dataId = dataId || uuid()
    // 引用id-脚注场景使用
    this.referId = referId
    // 注意：表头可能包含，中文，英文以及单位，内容仅包含文本段落textData
    // tbody中的td内容可能包含文本段落、列项混合，顺序按行文结构聚合, 包含除开表格之外的结构化块

    this.blockList = blockList.map((i) => new StdBlock(i))
    // 列合并-没有合并则为1
    this.colspan = colspan
    // 行合并-没有合并则为1
    this.rowspan = rowspan
    if (width) this.width = width
    if (height) this.height = height
  }
}

class StdTfootTd {
  constructor({ dataId, dataType, colspan = 1, rowspan = 1, noteList = [], isRevised = false, width, height }) {
    // 数据唯一标识
    this.dataId = dataId || uuid()
    // 数据类型-表注或者表脚注
    this.dataType = dataType
    this.noteList = noteList.map((i) => new StdNote(i))
    // 列合并-没有合并则为1
    this.colspan = colspan
    // 行合并-没有合并则为1
    this.rowspan = rowspan
    if (width) this.width = width
    if (height) this.height = height
  }
}

class StdTheadV2 {
  constructor(thead) {
    this.tr = thead?.tr?.filter(i=>i)?.map((cell) => new StdTrV2({ tdType: 'th', tdOrThDataList: cell?.th, dataId: cell?.dataId }))
    this.dataId = thead.dataId
  }
}

class StdTbodyV2 {
  constructor(tbody) {
    this.tr = tbody.tr?.filter(i=>i)?.map(
      (cell) =>
        new StdTrV2({
          tdType: 'td',
          tdOrThDataList: cell?.td,
          dataId: cell?.dataId
        })
    )
    this.dataId = tbody.dataId
  }
}

class StdTfootV2 {
  constructor(tfoot) {
    this.tr = tfoot.tr?.filter(i=>i)?.map(
      (cell) =>
        new StdTrV2({
          tdType: 'td',
          tdOrThDataList: cell?.td,
          isTfoot: true,
          dataId: cell?.dataId
        })
    )
    this.dataId = tfoot.dataId
  }
}

class StdTrV2 {
  // tdType: 'td' | 'th'
  constructor({ tdType = 'td', tdOrThDataList=[], isTfoot = false, dataId }) {
    this[tdType] = tdOrThDataList.map((i) => {
      return isTfoot ? new StdTfootTd(i) : new StdThOrTd(i)
    })
    this.dataId = dataId
  }
}

export class StdTableV2 {
  constructor(node, number) {
    this.node = node
    this.number = number || node.dataset.number
  }
  get data() {
    return this.parseTable(this.node, this.number)
  }
  parseTable(tableNode, tableNumber) {
    const res = {
      dataId: tableNode.dataset?.id,
      captionZh: {},
      captionEn: store.getters.languageType === 'both' ? {} : null,
      tableNumber,
      thead: {},
      tbody: {},
      tfoot: {},
      variableId:tableNode.getAttribute("data-variable-id"),
    }
    function parseCaption(node, attr = 'captionZh') {
      const title = node.querySelector('.caption')?.textContent || ''
      const unitDom = node.querySelector('.unit')
      const unit = unitDom ? unitDom.textContent : null
      res[attr] = {
        dataId: node.dataset?.id,
        title,
        unit
      }
      if (node.nextElementSibling) {
        if (node.nextElementSibling.localName === 'caption') {
          parseCaption(node.nextElementSibling, 'captionEn')
        } else if (node.nextElementSibling.localName === 'thead') {
          parseThead(node.nextElementSibling)
          if (node.nextElementSibling?.nextElementSibling?.localName === 'tbody') {
            parseTbody(node.nextElementSibling.nextElementSibling)
          }
          if (node.nextElementSibling?.nextElementSibling?.nextElementSibling?.localName === 'tfoot') {
            parseTfoot(node.nextElementSibling.nextElementSibling.nextElementSibling)
          }
        }
        if (node.nextElementSibling.localName === 'tbody') {
          parseTbody(node.nextElementSibling)
        }
        if (node.nextElementSibling?.nextElementSibling?.localName === 'tfoot') {
          parseTfoot(node.nextElementSibling.nextElementSibling)
        }
      }
    }

    function parseThead(node) {
      res.thead.dataId = node.dataset.id || uuid()
      if (node?.firstChild?.localName === 'tr') {
        parseTr(node.firstChild, true)
      }
    }

    function parseTbody(node) {
      res.tbody.dataId = node.dataset.id || uuid()
      if (node?.firstChild?.localName === 'tr') {
        parseTr(node.firstChild)
      }
    }

    function parseTr(node, fromThead = false) {
      if (node) {
        const trData = parseTd(node.firstElementChild, fromThead, node.dataset.id)
        if (fromThead) {
          res.thead.tr = res.thead.tr || []
          res.thead.tr.push(trData)
        } else {
          res.tbody.tr = res.tbody.tr || []
          res.tbody.tr.push(trData)
        }
        if (node.nextElementSibling) {
          parseTr(node.nextElementSibling, fromThead)
        }
      }
    }
    function parseTd(node, isTh = false, dataId = null) {
      const tdData = {
        dataId: dataId || uuid()
      }
      function parseTdBlock(child, _arr) {
        const attrMap = child?.dataset
        const dataType = attrMap?.type
        if (child.localName?.toLowerCase?.() === 'p' || dataType === 'paragraph') {
          let textData = new StdParagraphV2(child).data
          _arr.push({
            dataType: 'paragraph',
            blockId: attrMap?.blockId || uuid(),
            textData
          })
          if (child.nextElementSibling) {
            parseTdBlock(child.nextElementSibling, _arr)
          }
        }
      }

      function walk(node) {
        if (node) {
          const tdOrTh = isTh ? (tdData.th = tdData.th || []) : (tdData.td = tdData.td || [])
          const firstNode = node?.firstElementChild
          let blockList = []
          // 此处解析列项、图、段落等, 暂时使用paragraph调试数据
          if (firstNode?.localName?.toLowerCase?.() === 'p') {
            parseTdBlock(firstNode, blockList)
          } else {
            blockList = [
              {
                dataType: 'paragraph',
                dataId: firstNode?.dataset?.id || uuid(),
                textData: new StdTextsV2(firstNode).data
              }
            ]
          }
          const tdOrThData = {
            blockList,
            dataId: node.dataset.id || uuid(),
            rowspan: node.rowSpan || 1,
            colspan: node.colSpan || 1,
            width: node?.getBoundingClientRect?.()?.width || node.offsetWidth,
            height: node.offsetHeight
          }
          tdOrTh.push(tdOrThData)
          if (node.nextElementSibling) {
            walk(node.nextElementSibling)
          }
        }
      }
      walk(node)
      return tdData
    }

    function parseTfoot(node) {
      res.tfoot.tr = []
      res.tfoot.dataId = node.dataset.id || uuid()
      function parseNote(note, _arr) {
        if (note) {
          const attrs = note.dataset || {}
          let number = attrs.number
          if (attrs.type !== 'table_footnote') {
            // 表注
            _arr.push({
              contentNumber: number,
              dataId: attrs.noteId,
              shareId: attrs.shareId,
              referredId: attrs.referredId,
              dataType: attrs.type,
              dataLang: attrs.lang,
              textData: new StdNoteTextDataV2(note).data
            })
          } else {
            // 表脚注
            _arr.push({
              contentNumber: number,
              dataId: attrs.noteId,
              referredId: attrs.referredId,
              dataType: attrs.type,
              dataLang: attrs.lang,
              textData: new StdNoteTextDataV2(note, 'footnote').data
            })
          }
          if (note.nextElementSibling) {
            parseNote(note.nextElementSibling, _arr)
          }
        }
      }

      function parseTfootTr(tr) {
        const td = tr?.querySelector?.('td')
        if (!td) return
        const attrs = td?.dataset || {}
        let noteList = []
        parseNote(td.querySelector?.('p'), noteList)
        res.tfoot.tr.push({
          dataId: tr.dataset?.id || uuid(),
          td: [
            {
              dataId: attrs.id,
              colspan: td.colSpan,
              rowspan: 1,
              dataType: attrs.type,
              noteList,
              width: td?.getBoundingClientRect?.()?.width || td.offsetWidth,
              height: td.offsetHeight
            }
          ]
        })
        if (tr.nextElementSibling) {
          parseTfootTr(tr.nextElementSibling)
        }
      }
      parseTfootTr(node.firstChild)
    }

    function parse(node) {
      if (node.localName === 'table') {
        if (node.firstElementChild?.localName === 'caption') {
          parseCaption(node.firstElementChild)
          return
        }
      }
      throw new Error('错误的表格')
    }

    parse(tableNode)
    return res
  }
}
